package com.hframe.plugin.ueditor;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.hframe.Json.DataToJson;
import com.hframe.Json.JsonFiletr;
import com.hframe.Json.JsonToData;
import com.hframe.data.DRef;
import com.hframe.http.client.ResponseData;
import com.hframe.http.servlet.HttpSkipServlet;
import com.hframe.http.servlet.HttpSkipServletRequest;
import com.hframe.http.servlet.HttpSkipServletResponse;
import com.hframe.param.ParamFiletr;
import com.hframe.type.TArray;
import com.hframe.type.TEnum;
import com.hframe.type.TInt;
import com.hframe.type.TString;
import com.hframe.typefilter.EnumToName;
import com.hframe.typefilter.NameToEnum;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;

/**
 * Created by heqian on 17-10-25.
 */
public class Controller extends HttpSkipServlet {
    private static Logger log = Logger.getLogger(Controller.class);
    DConfig config = null;

    public static class DataParam extends DRef<DataParam> {
        TEnum<EnumAction> action = new TEnum<>(EnumAction.class);
        TInt start = new TInt();
        TInt size = new TInt();

        public DataParam() {
            action.filter(ParamFiletr.class).setSetCall(new NameToEnum(EnumAction.class));
        }
    }

    protected DConfig readConfig() {
        String propertiesPath = this.getClass().toString();
        int index = propertiesPath.lastIndexOf(".");
        propertiesPath = propertiesPath.substring(index + 1, propertiesPath.length());
        try {
            InputStream in = this.getClass().getResourceAsStream(propertiesPath + ".json");
            JsonElement json = new JsonParser().parse(new InputStreamReader(in));
            in.close();

            DConfig ret = new DConfig();
            JsonToData.convert(json, ret);

            return ret;
        } catch (Exception e) {
            log.error(e, e);
        }
        return null;
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (null == config) {
            config = readConfig();
        }
        super.service(request, response);
    }

    public static class DataReturn extends DRef<DataReturn> {
        TEnum<EnumState> state = new TEnum<>(EnumState.SUCCESS);

        public DataReturn() {
            state.filter(JsonFiletr.class).setGetCall(new EnumToName<>());
        }
    }

    public static class DataImage extends DRef<DataImage> {
        TString url = new TString();

        public DataImage(String url) {
            this.url.set(url);
        }
    }

    public static class DataListImage extends DataReturn {
        public TArray<DataImage> list = new TArray<>(DataImage.class);
        public TInt start = new TInt();
        public TInt total = new TInt();
    }

    @Override
    protected boolean DoGet(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        try {
            JsonElement json = null;
            DataParam param = request.getParameter(new DataParam());
            switch (param.action.get()) {
                case Config:
                    DConfig con = getConfig();
                    con.catcherActionName.set(EnumAction.CatchImage);
                    con.fileManagerActionName.set(EnumAction.ListFile);
                    con.imageActionName.set(EnumAction.UploadImage);
                    con.imageManagerActionName.set(EnumAction.ListImage);
                    con.scrawlActionName.set(EnumAction.UploadScrawl);
                    con.videoActionName.set(EnumAction.UploadVideo);
                    json = DataToJson.convert(con);
                    break;

                case ListImage:
                    json = DataToJson.convert(onListImage(request, response, param.start.get(), param.size.get()));
                    break;

            }

            response.getOutputStream().write(json.toString().getBytes("UTF-8"));
        } catch (Exception e) {
            response.write(new ResponseData(-1, "服务器内部错误"));
        }
        return false;
    }

    protected DataListImage onListImage(HttpSkipServletRequest request, HttpSkipServletResponse response, Integer start, Integer size) {
        return null;
    }

    protected DConfig getConfig() {
        return config;
    }

    public static class DataUploadReturn extends DataReturn {
        public TString url = new TString();
        public TString title = new TString();
        public TString original = new TString();
    }


    @Override
    protected boolean DoPost(HttpSkipServletRequest request, HttpSkipServletResponse response) throws ServletException, IOException {
        try {
            JsonElement json = null;
            DataReturn uploadReturn = null;
            DataParam param = request.getParameter(new DataParam());
            switch (param.action.get()) {
                case UploadImage:
                    uploadReturn = onUploadImage(request, response);
                    break;
                case UploadVideo:
                    uploadReturn = onUploadVideo(request, response);
                    break;
                case UploadFile:
                    uploadReturn = onUploadFile(request, response);
                    break;
                case CatchImage:
                    uploadReturn = onCatchImage(request, response);
                    break;
                case UploadScrawl:
                    uploadReturn = onUploadScrawl(request, response);
                    break;
            }

            json = DataToJson.convert(uploadReturn);
            response.getOutputStream().write(json.toString().getBytes("UTF-8"));
        } catch (Exception e) {
            response.write(new ResponseData(-1, "服务器内部错误"));
        }
        return false;
    }

    protected DataUploadReturn onUploadScrawl(HttpSkipServletRequest request, HttpSkipServletResponse response) throws Exception {
        String base64 = request.getParameter(config.scrawlFieldName.get());
        File file = new File(getServletContext().getRealPath(config.scrawlPathFormat.get()));
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }

        String name = new Date().toString() + ".jpg";
        file = new File(file.getPath() + name);
        saveScrawl(base64, file);
        DataUploadReturn ret = new DataUploadReturn();

        ret.url.set(config.scrawlPathFormat.get() + name);
        ret.title.set(name);
        ret.original.set(name);
        return ret;
    }

    protected void saveScrawl(String base64, File file) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        decoder.decodeBuffer(new ByteArrayInputStream(base64.getBytes()), new FileOutputStream(file));
    }

    protected DataUploadReturn onUploadFile(HttpSkipServletRequest request, HttpSkipServletResponse response) throws Exception {
        UploadFile upload = new UploadFile(
                getServletContext(),
                config.filePathFormat.get(),
                config.fileMaxSize.get(),
                config.fileAllowFiles.get());
        upload.upload(request);

        DataUploadReturn ret = new DataUploadReturn();
        ret.url.set(config.filePathFormat.get() + upload.getFileName());
        ret.title.set(upload.getFileName());
        ret.original.set(upload.getFileName());
        return ret;
    }

    protected DataUploadReturn onUploadVideo(HttpSkipServletRequest request, HttpSkipServletResponse response) throws Exception {
        UploadFile upload = new UploadFile(
                getServletContext(),
                config.videoPathFormat.get(),
                config.videoMaxSize.get(),
                config.videoAllowFiles.get());
        upload.upload(request);

        DataUploadReturn ret = new DataUploadReturn();
        ret.url.set(config.videoPathFormat.get() + upload.getFileName());
        ret.title.set(upload.getFileName());
        ret.original.set(upload.getFileName());
        return ret;
    }

    protected DataUploadReturn onCatchImage(HttpSkipServletRequest request, HttpSkipServletResponse response) throws Exception {

        DataUploadReturn ret = new DataUploadReturn();
//        ret.url.set(upload.getFilePath());
//        ret.title.set(upload.getFileName());
//        ret.original.set(upload.getFileName());
        return ret;
    }


    protected DataUploadReturn onUploadImage(HttpSkipServletRequest request, HttpSkipServletResponse response) throws Exception {
        UploadFile upload = new UploadFile(
                getServletContext(),
                config.imagePathFormat.get(),
                config.imageMaxSize.get(),
                config.imageAllowFiles.get());
        upload.upload(request);

        DataUploadReturn ret = new DataUploadReturn();
        ret.url.set(config.imagePathFormat.get() + upload.getFileName());
        ret.title.set(upload.getFileName());
        ret.original.set(upload.getFileName());
        return ret;
    }

}
